package com.aspirecn.core.client;

import java.io.InputStream;
import java.util.Iterator;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.http.HttpServletResponse;

import jodd.cache.Cache;
import jodd.cache.LRUCache;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;

import com.aspirecn.core.commons.Configuration;
import com.aspirecn.core.object.ShortURL;

/**
 * 短地址调用客户端
 * 每个客户端最大并发3个连接
 * @author wangxinning
 *
 */
public class ShortURLClient {

	//http请求时间限制
	private final static int ConnectionTimeout = 3000;
	private final static int SoTimeout = 3000;	
	//最大连接的线程同步变量
	private static AtomicInteger current_connection_count = new AtomicInteger(0);
	//最大连接数
	private final static int CONNECTION_SIZE = 5;	
	//缓存最大数
	private final static int CACHE_SIZE = 5000;	
	//本地缓存
	private static Cache<String,ShortURL> localShortURLService = new LRUCache<String,ShortURL>(CACHE_SIZE);
	
	/**
	 * 自定义短地址接口
	 * key:接口密钥
	 * longUrl:长地址
	 * userShort:自定义短地址
	 * @param args
	 */
	public static ShortURL alias(String key, String longUrl, String userShort) {
		
		ShortURL retObj = null;
		int count = current_connection_count.incrementAndGet();
		if( count <= CONNECTION_SIZE )
		{
			//逻辑处理			
			String apiurl = Configuration.getInstance().getShorturlUrl() + "alias.do";			
			
			Properties pro = new Properties();
			pro.setProperty("key", key);
			pro.setProperty("longUrl", longUrl);
			pro.setProperty("userShort", userShort);

			try
			{
				String content = urlToStr(apiurl, "utf-8", pro);
				
				retObj = new ShortURL();
				retObj.load(content);		
			}
			catch( Exception e )
			{
				e.printStackTrace();
			}
		}
		current_connection_count.decrementAndGet();
		return retObj;
	}
	
	/**
	 * 短地址还原，根据短地址查询长地址
	 * @param key
	 * @param userShort
	 * @return
	 */
	public static ShortURL expand(String key, String userShort) {
		
		ShortURL retObj = localShortURLService.get(userShort);		
		if( retObj != null )
		{
			return retObj;
		}
		
		int count = current_connection_count.incrementAndGet();
		if( count <= CONNECTION_SIZE )
		{
			String apiurl = Configuration.getInstance().getShorturlUrl() + "expand.do";

			Properties pro = new Properties();
			pro.setProperty("key", key);
			pro.setProperty("userShort", userShort);

			try
			{
				String content = urlToStr(apiurl, "utf-8", pro);
				
				retObj = new ShortURL();
				retObj.load(content);
				
				//缓存处理
				if( retObj.getStatus() == ShortURL.OK )
				{
					localShortURLService.put(retObj.getLongUrl(), retObj);
					localShortURLService.put(userShort, retObj);
				}
			}
			catch( Exception e )
			{
				e.printStackTrace();
			}
		}
		current_connection_count.decrementAndGet();
		return retObj;
	}
	
	
	/**
	 * 长地址自动缩短
	 * @param key
	 * @param longUrl
	 * @return
	 */
	public static ShortURL shorten(String key, String longUrl) {
		
		ShortURL retObj = localShortURLService.get(longUrl);		
		if( retObj != null )
		{
			return retObj;
		}
		
		int count = current_connection_count.incrementAndGet();
		if( count <= CONNECTION_SIZE )
		{
			String apiurl = Configuration.getInstance().getShorturlUrl() + "shorten.do";
			
			Properties pro = new Properties();
			pro.setProperty("key", key);
			pro.setProperty("longUrl", longUrl);

			try
			{
				String content = urlToStr(apiurl, "utf-8", pro);
				
				retObj = new ShortURL();
				retObj.load(content);
				
				//缓存处理
				if( retObj.getStatus() == ShortURL.OK )
				{
					localShortURLService.put(longUrl, retObj);
					localShortURLService.put(retObj.getUserShort(), retObj);
				}
			}
			catch( Exception e )
			{
				e.printStackTrace();
			}
		}
		current_connection_count.decrementAndGet();
		return retObj;
	}
	
	
	/**
	 * 接口请求的方法
	 * @param url
	 * @param encode
	 * @param pro
	 * @return
	 * @throws Exception
	 */
	private static String urlToStr(String url, String encode, Properties pro)
			throws Exception {
		PostMethod post = null;
		HttpClient client = new HttpClient();
		InputStream is = null;
		String str = null;
		Exception e = null;

		try {
			post = new PostMethod(url);

			Iterator<Object> ite = pro.keySet().iterator();
			while (ite.hasNext()) {
				String key = ite.next().toString();
				post.addParameter(key, pro.getProperty(key));
			}

			client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
					new DefaultHttpMethodRetryHandler());
			client.getParams().setParameter(
					HttpMethodParams.HTTP_CONTENT_CHARSET, encode);
			// client.getParams().setParameter(HttpMethodParams.USER_AGENT,userAgent);

			HttpConnectionManagerParams managerParams = client
					.getHttpConnectionManager().getParams();
			managerParams.setConnectionTimeout(ConnectionTimeout);
			managerParams.setSoTimeout(SoTimeout);
			int status = client.executeMethod(post);

			if (status == HttpServletResponse.SC_OK) {

				is = post.getResponseBodyAsStream();
				str = IOUtils.toString(is, encode);
			}

		} catch (Exception ee) {

			ee.printStackTrace();
			e = ee;

		} finally {
			IOUtils.closeQuietly(is);
			if (post != null) {
				post.releaseConnection();
			}
			client.getHttpConnectionManager().closeIdleConnections(0);
		}

		if (e != null) {
			throw e;
		}

		return str;
	}
}
